/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/common.hpp>
#include <baja/graphics.hpp>
#include <baja/math.hpp>
#include <journal/app/constants.h>

namespace journal { namespace view {

namespace b = baja;
namespace g = baja::graphics;
namespace m = baja::math;

// re. paddings: see msdn for hlsl constant buffer packing rules (packed to 4 byte boundaries)
// I am sure there're better ways to do this than to insert paddings but this works just fine for now.
// bottom line make sure nothing crosses a 4 byte boundary
struct quad_constants
{
    m::point4d rotation;
    m::point2d origin;
    b::float32 alpha;
    b::float32 padding_1;
    m::point2d targetDimensions; 
    m::point2d dimensions;
    m::point2d context;
    b::float32 padding[2];
};

enum class post_processing_effect
{
    none = 0,
    vertical_blur,
    horizontal_blur,
    darken,
    lasso
};

class quad_renderer
{
private:
    struct quad_vertex
    {
        m::point2d position;
        m::point2d uv;
    };

public:
    quad_renderer() : _initialized(false) {}
    static std::shared_ptr<quad_renderer> create();
    static std::shared_ptr<quad_renderer> singleton();

    void render(
        const b::float32 alpha,
        const b::float32 angle,
        const m::point2d targetDimensions,
        const m::point2d dimensions,
        const m::point2d origin,
        const std::shared_ptr<g::itexture>& texture,
        const post_processing_effect ppe = post_processing_effect::none,
        const bool writeAlpha = true,
        const void* context = nullptr
        );

private:
    void ensureInitialized(const post_processing_effect ppe);
    std::shared_ptr<g::ieffect2> ensureEffectInitialized(
        const b::wchar* name, 
        const b::wchar* pixelShader, 
        const b::wchar* vertexShader
        );

private:
    bool _initialized;
    static std::shared_ptr<quad_renderer> _singleton;

    std::shared_ptr<g::ieffect2> _quadEffect;
    std::shared_ptr<g::ieffect2> _quadHBlurEffect;
    std::shared_ptr<g::ieffect2> _quadVBlurEffect;
    std::shared_ptr<g::ieffect2> _quadDarkenEffect;
    std::shared_ptr<g::ieffect2> _lassoEffect;

    std::shared_ptr<g::ivertex_declaration> _quadVertexDeclaration;
    std::shared_ptr<g::ivertex_buffer> _quadVertexBuffer;
};

}}